Skip to content

Improve _normalizeAngle speed.#530

Draft
jaguilar wants to merge 1 commit intosimplefoc:devfrom
jaguilar:opt_normalize_angle
Draft

Improve _normalizeAngle speed.#530
jaguilar wants to merge 1 commit intosimplefoc:devfrom
jaguilar:opt_normalize_angle

Conversation

@jaguilar
Copy link
Copy Markdown

Description

Previously _normalizeAngle used fmodf, which is expensive on Cortex-M series chips (40-100 cycles). For normalizing the angle, we can use a trick of just subtracking 2 pi times the number of full rotations from the angle.

This method does lose precision much faster than the fmodf approach. There will be significant error if the total number of radians passed in is greater than 10^5. However, we can counteract this by not passing in such a large number of radians -- basically making sure that we are not using an accumulating radian count in any location where the angle will eventually need to be normalized. This should typically be the case since accumulating radian use cases are definitionally not in need of normalization. We should consider adding an assert here to ensure that we catch any existing cases where we should be passing the mechanical or electrical angle and are instead passing an accumulator.

Performance test (on STM32G474, with certain other optimizations):

Before: foc_nanos:13737
After: foc_nanos:12550 (approx 9% reduction in loopFOC time)

Type of change

  • Optimization

How Has This Been Tested?

I built an arduino-foc-based test program based on this commit and observed that the motor still worked fine. I also benchmarked the code and observed it to be faster. I have not tested all possible control modes so it is not impossible that this approach is unacceptable in some configurations. Please review carefully and suggest anything further that I should check.

Test Configuration/Setup:

  • Hardware: STM32G474 with custom gate driver board
  • IDE: STM32CubeMX/VSCode/CMake
  • MCU package version (stm32duino/arduino-esp32/..): N/A, using my own custom Arduino shims

Previously _normalizeAngle used fmodf, which is expensive on Cortex-M
series chips (40-100 cycles). For normalizing the angle, we can use
a trick of just subtracking 2 pi times the number of full rotations from
the angle.

This method does lose precision much faster than the fmodf approach.
There will be significant error if the total number of radians passed
in is greater than 10^5. However, we can counteract this by not passing
in such a large number of radians -- basically making sure that we are
not using an accumulating radian count in any location where the angle
will eventually need to be normalized. This should typically be the case
since accumulating radian use cases are definitionally not in need of
normalization. We should consider adding an assert here to ensure
that we catch any existing cases where we should be passing the
mechanical or electrical angle and are instead passing an accumulator.

Performance test (on STM32G474, with certain other optimizations):

Before:   foc_nanos:13737
After:    foc_nanos:12550 (approx 9% reduction in loopFOC time)
}
// Normalize the shaft angle after each iteration to prevent it growing indefinitely
// and eventually losing precision.
shaft_angle = _normalizeAngle(shaft_angle);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did you test this? It seems to me we’ll never reach the target as shaft-angle is used to track the current position in open loop angle mode?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This part was not tested with angles greater than 2PI. I agree that if the user sets angles outside the range, it wouldn't work. We should probably also normalize the target angle beforehand. WDYT?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants